use serde::Serialize;
use serde::Serializer;
use std::time::Duration;
use super::state::PlaybackStatus;

pub(crate) fn serialize_duration_as_millis<S>(duration: &Duration, serializer: S) -> Result<S::Ok, S::Error>
where
    S: Serializer,
{
    serializer.serialize_u64(duration.as_millis() as u64)
}

#[derive(Debug, Clone, Serialize)]
#[serde(tag = "type", rename_all = "camelCase")]
pub enum PlayerEvent {
    // 媒体信息事件
    MediaOpened {
        video_info: Option<VideoInfo>,
        audio_info: Option<AudioInfo>,
        #[serde(serialize_with = "serialize_duration_as_millis")]
        duration: Duration,
    },
    MediaClosed,

    // 播放状态事件
    PlaybackStarted,
    PlaybackResumed,
    PlaybackPaused,
    PlaybackStopped,
    StatusChanged(PlaybackStatus),
    PositionChanged {
        #[serde(serialize_with = "serialize_duration_as_millis")]
        position: Duration,
        #[serde(serialize_with = "serialize_duration_as_millis")]
        duration: Duration,
    },
    BufferingProgress {
        progress: f32,
    },

    // 媒体帧事件
    VideoFrame {
        width: u32,
        height: u32,
        data: Vec<u8>,
        #[serde(serialize_with = "serialize_duration_as_millis")]
        timestamp: Duration,
        #[serde(serialize_with = "serialize_duration_as_millis")]
        duration: Duration,
    },
    AudioFrame {
        data: Vec<f32>,
        channels: u32,
        sample_rate: u32,
        #[serde(serialize_with = "serialize_duration_as_millis")]
        timestamp: Duration,
        #[serde(serialize_with = "serialize_duration_as_millis")]
        duration: Duration,
    },

    // 音频控制事件
    VolumeChanged {
        volume: f32,
        muted: bool,
    },
    SpeedChanged(f32),

    // 错误事件
    Error {
        code: i32,
        message: String,
        details: Option<String>,
    },
}

#[derive(Debug, Clone, Serialize)]
pub struct VideoInfo {
    pub width: u32,
    pub height: u32,
    pub frame_rate: f64,
    #[serde(serialize_with = "serialize_duration_as_secs")]
    pub duration: Duration,
    pub codec: String,
    pub bit_rate: Option<u64>,
}

#[derive(Debug, Clone, Serialize)]
pub struct AudioInfo {
    pub channels: u32,
    pub sample_rate: u32,
    #[serde(serialize_with = "serialize_duration_as_secs")]
    pub duration: Duration,
    pub codec: String,
    pub bit_rate: Option<u64>,
}

fn serialize_duration_as_secs<S>(duration: &Duration, serializer: S) -> Result<S::Ok, S::Error>
where
    S: serde::Serializer,
{
    serializer.serialize_f64(duration.as_secs_f64())
}

// 添加事件发送辅助函数
impl PlayerEvent {
    pub fn send(&self, window: &tauri::Window) -> anyhow::Result<()> {
        window.emit("player-event", self)
            .map_err(|e| anyhow::anyhow!("Failed to send event: {}", e))
    }
}

// 事件发送辅助函数
pub fn send_event(window: &tauri::Window, event: PlayerEvent) -> anyhow::Result<()> {
    log::debug!("Sending event: {:?}", event);
    event.send(window)
}

pub fn send_media_opened(
    window: &tauri::Window,
    video_info: Option<VideoInfo>,
    audio_info: Option<AudioInfo>,
    duration: Duration,
) -> anyhow::Result<()> {
    send_event(window, PlayerEvent::MediaOpened {
        video_info,
        audio_info,
        duration,
    })
}

pub fn send_position_changed(
    window: &tauri::Window,
    position: Duration,
    duration: Duration,
) -> anyhow::Result<()> {
    send_event(window, PlayerEvent::PositionChanged {
        position,
        duration,
    })
}

pub fn send_error(
    window: &tauri::Window,
    code: i32,
    message: impl Into<String>,
    details: Option<String>,
) -> anyhow::Result<()> {
    send_event(window, PlayerEvent::Error {
        code,
        message: message.into(),
        details,
    })
}

pub fn send_playback_status(
    window: &tauri::Window,
    status: PlaybackStatus,
) -> anyhow::Result<()> {
    send_event(window, PlayerEvent::StatusChanged(status))
}

pub fn send_volume_changed(
    window: &tauri::Window,
    volume: f32,
    muted: bool,
) -> anyhow::Result<()> {
    send_event(window, PlayerEvent::VolumeChanged {
        volume,
        muted,
    })
}

pub fn send_video_frame(
    window: &tauri::Window,
    width: u32,
    height: u32,
    data: Vec<u8>,
    timestamp: Duration,
    duration: Duration,
) -> anyhow::Result<()> {
    send_event(window, PlayerEvent::VideoFrame {
        width,
        height,
        data,
        timestamp,
        duration,
    })
}

pub fn send_audio_frame(
    window: &tauri::Window,
    data: Vec<f32>,
    channels: u32,
    sample_rate: u32,
    timestamp: Duration,
    duration: Duration,
) -> anyhow::Result<()> {
    send_event(window, PlayerEvent::AudioFrame {
        data,
        channels,
        sample_rate,
        timestamp,
        duration,
    })
}
